#ifndef PROCESS_STATE_H
#define PROCESS_STATE_H
#include "constants.h"
#include "graph.h"
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <set>
#include "set_int.h"

struct PotentialDegree
{
    size_t degree[SIZE_VMSK];
    MaxValueSet<SIZE_VMSK> degreeSet;

    void init(const IGraph* newGraph)
    {
        for(size_t u = 0; u < SIZE_VMSK; ++u) {
            degree[u] = newGraph->degree(u);
            degreeSet.add(degree[u]);
        }
    }
};

struct ColorInfo
{
    size_t color[SIZE_VMSK];
    MaxValueSet<n + 2> maxColor;
    MinOutValueSet<n + 2> neighbours[SIZE_VMSK];

    void init(const IGraph* newGraph)
    {
        for(size_t u = 0; u < SIZE_VMSK; ++u) {
            for(size_t v = 0; v < u; ++v) {
                if (newGraph->isConnected(u, v)) {
                    neighbours[u].add(color[v]);
                }
            }
            color[u] = std::min(neighbours[u].minOutside(), n + 2);
            maxColor.add(color[u]);
        }
    }
};

struct ProcessState
{
    explicit ProcessState(const IGraph* g, const IGraph* ng, size_t dist)
        :graph(g), newGraph(ng), dist(dist)
    {
        numVerteciesWithLargestBit = (1 << (n - 1));
        memset(getted, 255, sizeof(getted));
        memset(getDegree, 0, sizeof(getDegree));
        for(size_t u = 0; u < SIZE_VMSK; ++u) {
             notGetDegree[u] = notProcessedDegree[u] = g->degree(u);
        }
        for(size_t u = 0; u < SIZE_VMSK; ++u) {
            if (g->degree(u) == 0) {
                getted[u] = 0;
            }
        }
        potentialDegree.init(newGraph);
        colorInfo.init(newGraph);
        numVertecies = 0;
    }

    const IGraph* const graph;
    const IGraph* subGraph;
    const IGraph* newGraph;
    
    //!List of vertecies taken to the graph.
    size_t numVertecies;
    size_t vertecies[SIZE_VMSK];

    //!Number of neighbours in vertecies.
    size_t getDegree[SIZE_VMSK];
    //!Number of neighbours not in vertecies.
    size_t notGetDegree[SIZE_VMSK];
    //!Number of neighbours, which can be added to graph in following process.
    size_t notProcessedDegree[SIZE_VMSK];
    //!Number of neighbours, which can be added to graph looking in new graph.

    PotentialDegree potentialDegree;
    ColorInfo colorInfo;

    //!Is vertex getted to graph. -1 is unknown
    int getted[SIZE_VMSK];
    //!Number of vertecies, which has the largest bit
    size_t numVerteciesWithLargestBit;

    size_t dist;
};


#endif//PROCESS_STATE_H
